#include "Vault_t.h"

#include "sgx_trts.h" /* for sgx_ocalloc, sgx_is_outside_enclave */
#include "sgx_lfence.h" /* for sgx_lfence */

#include <errno.h>
#include <mbusafecrt.h> /* for memcpy_s etc */
#include <stdlib.h> /* for malloc/free etc */

#define CHECK_REF_POINTER(ptr, siz) do {	\
	if (!(ptr) || ! sgx_is_outside_enclave((ptr), (siz)))	\
		return SGX_ERROR_INVALID_PARAMETER;\
} while (0)

#define CHECK_UNIQUE_POINTER(ptr, siz) do {	\
	if ((ptr) && ! sgx_is_outside_enclave((ptr), (siz)))	\
		return SGX_ERROR_INVALID_PARAMETER;\
} while (0)

#define CHECK_ENCLAVE_POINTER(ptr, siz) do {	\
	if ((ptr) && ! sgx_is_within_enclave((ptr), (siz)))	\
		return SGX_ERROR_INVALID_PARAMETER;\
} while (0)


typedef struct ms_initVault_t {
	int ms_retval;
	const char* ms_id;
	size_t ms_id_len;
} ms_initVault_t;

typedef struct ms_uninitVault_t {
	int ms_retval;
	const char* ms_id;
	size_t ms_id_len;
} ms_uninitVault_t;

typedef struct ms_encrypt_t {
	int ms_retval;
	const char* ms_id;
	size_t ms_id_len;
	const char* ms_in_buf;
	int ms_in_buf_len;
	char* ms_out_buf;
	int ms_out_buf_size;
} ms_encrypt_t;

typedef struct ms_encrypt_size_t {
	int ms_retval;
	const char* ms_id;
	size_t ms_id_len;
	int ms_buf_len;
} ms_encrypt_size_t;

typedef struct ms_encryptex_t {
	int ms_retval;
	const char* ms_id;
	size_t ms_id_len;
	const char* ms_in_buf;
	int ms_in_buf_len;
	const int* ms_value_lens;
	const int* ms_value_types;
	int ms_value_count;
	char* ms_out_buf;
	int ms_out_buf_size;
	int* ms_out_value_lens;
} ms_encryptex_t;

typedef struct ms_decrypt_t {
	int ms_retval;
	const char* ms_id;
	size_t ms_id_len;
	const char* ms_in_buf;
	int ms_in_buf_len;
	char* ms_out_buf;
	int ms_out_buf_size;
} ms_decrypt_t;

typedef struct ms_public_key_encrypt_t {
	int ms_retval;
	const char* ms_id;
	size_t ms_id_len;
	const char* ms_in_buf;
	int ms_in_buf_len;
	char* ms_out_buf;
	int ms_out_buf_size;
} ms_public_key_encrypt_t;

typedef struct ms_private_key_decrypt_t {
	int ms_retval;
	const char* ms_id;
	size_t ms_id_len;
	const char* ms_in_buf;
	int ms_in_buf_len;
	char* ms_out_buf;
	int ms_out_buf_size;
} ms_private_key_decrypt_t;

typedef struct ms_private_key_encrypt_t {
	int ms_retval;
	const char* ms_id;
	size_t ms_id_len;
	const char* ms_in_buf;
	int ms_in_buf_len;
	char* ms_out_buf;
	int ms_out_buf_size;
} ms_private_key_encrypt_t;

typedef struct ms_public_key_decrypt_t {
	int ms_retval;
	const char* ms_id;
	size_t ms_id_len;
	const char* ms_in_buf;
	int ms_in_buf_len;
	char* ms_out_buf;
	int ms_out_buf_size;
} ms_public_key_decrypt_t;

typedef struct ms_sign_t {
	int ms_retval;
	const char* ms_id;
	size_t ms_id_len;
	const char* ms_in_buf;
	int ms_in_buf_len;
	char* ms_out_buf;
	int ms_out_buf_size;
} ms_sign_t;

typedef struct ms_sha256_encrytp_t {
	int ms_retval;
	const char* ms_id;
	size_t ms_id_len;
	const char* ms_in_buf;
	int ms_in_buf_len;
	char* ms_out_buf;
	int ms_out_buf_size;
} ms_sha256_encrytp_t;

typedef struct ms_crypto_key_t {
	int ms_retval;
	const char* ms_id;
	size_t ms_id_len;
	char* ms_key;
	int ms_key_len;
} ms_crypto_key_t;

typedef struct ms_sgx_oc_cpuidex_t {
	int* ms_cpuinfo;
	int ms_leaf;
	int ms_subleaf;
} ms_sgx_oc_cpuidex_t;

typedef struct ms_sgx_thread_wait_untrusted_event_ocall_t {
	int ms_retval;
	const void* ms_self;
} ms_sgx_thread_wait_untrusted_event_ocall_t;

typedef struct ms_sgx_thread_set_untrusted_event_ocall_t {
	int ms_retval;
	const void* ms_waiter;
} ms_sgx_thread_set_untrusted_event_ocall_t;

typedef struct ms_sgx_thread_setwait_untrusted_events_ocall_t {
	int ms_retval;
	const void* ms_waiter;
	const void* ms_self;
} ms_sgx_thread_setwait_untrusted_events_ocall_t;

typedef struct ms_sgx_thread_set_multiple_untrusted_events_ocall_t {
	int ms_retval;
	const void** ms_waiters;
	size_t ms_total;
} ms_sgx_thread_set_multiple_untrusted_events_ocall_t;

typedef struct ms_ocall_get_string_t {
	char* ms_buf;
	int ms_len;
} ms_ocall_get_string_t;

typedef struct ms_ocall_print_string_t {
	const char* ms_string;
} ms_ocall_print_string_t;

typedef struct ms_ocall_log_info_t {
	const char* ms_buf;
} ms_ocall_log_info_t;

typedef struct ms_ocall_log_warning_t {
	const char* ms_buf;
} ms_ocall_log_warning_t;

typedef struct ms_ocall_log_error_t {
	const char* ms_buf;
} ms_ocall_log_error_t;

typedef struct ms_ocall_log_fatal_t {
	const char* ms_buf;
} ms_ocall_log_fatal_t;

typedef struct ms_ocall_fopen_t {
	int ms_retval;
	_int64* ms_file;
	const char* ms_file_name;
	const char* ms_mode;
} ms_ocall_fopen_t;

typedef struct ms_ocall_fclose_t {
	int ms_retval;
	_int64 ms_file;
} ms_ocall_fclose_t;

typedef struct ms_ocall_fputs_t {
	int ms_retval;
	_int64 ms_file;
	const char* ms_buf;
} ms_ocall_fputs_t;

typedef struct ms_ocall_fseek_t {
	int ms_retval;
	_int64 ms_file;
	long int ms_offset;
	int ms_origin;
} ms_ocall_fseek_t;

typedef struct ms_ocall_ftell_t {
	long int ms_retval;
	_int64 ms_file;
} ms_ocall_ftell_t;

typedef struct ms_ocall_fread_t {
	size_t ms_retval;
	_int64 ms_file;
	void* ms_buf;
	int ms_buf_len;
	size_t ms_element_size;
	size_t ms_element_count;
} ms_ocall_fread_t;

typedef struct ms_ocall_fgets_t {
	char* ms_retval;
	_int64 ms_file;
	char* ms_buf;
	int ms_buf_len;
} ms_ocall_fgets_t;

typedef struct ms_ocall_is_dir_exsit_t {
	int ms_retval;
	const char* ms_dri_name;
} ms_ocall_is_dir_exsit_t;

typedef struct ms_ocall_make_dir_t {
	int ms_retval;
	const char* ms_dir_name;
} ms_ocall_make_dir_t;

typedef struct ms_u_sgxssl_ftime64_t {
	void* ms_timeptr;
	uint32_t ms_timeb64Len;
} ms_u_sgxssl_ftime64_t;

#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4127)
#pragma warning(disable: 4200)
#endif

static sgx_status_t SGX_CDECL sgx_initVault(void* pms)
{
	CHECK_REF_POINTER(pms, sizeof(ms_initVault_t));
	//
	// fence after pointer checks
	//
	sgx_lfence();
	ms_initVault_t* ms = SGX_CAST(ms_initVault_t*, pms);
	sgx_status_t status = SGX_SUCCESS;
	const char* _tmp_id = ms->ms_id;
	size_t _len_id = ms->ms_id_len ;
	char* _in_id = NULL;

	CHECK_UNIQUE_POINTER(_tmp_id, _len_id);

	//
	// fence after pointer checks
	//
	sgx_lfence();

	if (_tmp_id != NULL && _len_id != 0) {
		_in_id = (char*)malloc(_len_id);
		if (_in_id == NULL) {
			status = SGX_ERROR_OUT_OF_MEMORY;
			goto err;
		}

		if (memcpy_s((void*)_in_id, _len_id, _tmp_id, _len_id)) {
			status = SGX_ERROR_UNEXPECTED;
			goto err;
		}

		_in_id[_len_id - 1] = '\0';
		if (_len_id != strlen(_in_id) + 1)
		{
			status = SGX_ERROR_UNEXPECTED;
			goto err;
		}
	}

	ms->ms_retval = initVault((const char*)_in_id);
err:
	if (_in_id) free((void*)_in_id);

	return status;
}

static sgx_status_t SGX_CDECL sgx_uninitVault(void* pms)
{
	CHECK_REF_POINTER(pms, sizeof(ms_uninitVault_t));
	//
	// fence after pointer checks
	//
	sgx_lfence();
	ms_uninitVault_t* ms = SGX_CAST(ms_uninitVault_t*, pms);
	sgx_status_t status = SGX_SUCCESS;
	const char* _tmp_id = ms->ms_id;
	size_t _len_id = ms->ms_id_len ;
	char* _in_id = NULL;

	CHECK_UNIQUE_POINTER(_tmp_id, _len_id);

	//
	// fence after pointer checks
	//
	sgx_lfence();

	if (_tmp_id != NULL && _len_id != 0) {
		_in_id = (char*)malloc(_len_id);
		if (_in_id == NULL) {
			status = SGX_ERROR_OUT_OF_MEMORY;
			goto err;
		}

		if (memcpy_s((void*)_in_id, _len_id, _tmp_id, _len_id)) {
			status = SGX_ERROR_UNEXPECTED;
			goto err;
		}

		_in_id[_len_id - 1] = '\0';
		if (_len_id != strlen(_in_id) + 1)
		{
			status = SGX_ERROR_UNEXPECTED;
			goto err;
		}
	}

	ms->ms_retval = uninitVault((const char*)_in_id);
err:
	if (_in_id) free((void*)_in_id);

	return status;
}

static sgx_status_t SGX_CDECL sgx_encrypt(void* pms)
{
	CHECK_REF_POINTER(pms, sizeof(ms_encrypt_t));
	//
	// fence after pointer checks
	//
	sgx_lfence();
	ms_encrypt_t* ms = SGX_CAST(ms_encrypt_t*, pms);
	sgx_status_t status = SGX_SUCCESS;
	const char* _tmp_id = ms->ms_id;
	size_t _len_id = ms->ms_id_len ;
	char* _in_id = NULL;
	const char* _tmp_in_buf = ms->ms_in_buf;
	int _tmp_in_buf_len = ms->ms_in_buf_len;
	size_t _len_in_buf = _tmp_in_buf_len;
	char* _in_in_buf = NULL;
	char* _tmp_out_buf = ms->ms_out_buf;
	int _tmp_out_buf_size = ms->ms_out_buf_size;
	size_t _len_out_buf = _tmp_out_buf_size;
	char* _in_out_buf = NULL;

	CHECK_UNIQUE_POINTER(_tmp_id, _len_id);
	CHECK_UNIQUE_POINTER(_tmp_in_buf, _len_in_buf);
	CHECK_UNIQUE_POINTER(_tmp_out_buf, _len_out_buf);

	//
	// fence after pointer checks
	//
	sgx_lfence();

	if (_tmp_id != NULL && _len_id != 0) {
		_in_id = (char*)malloc(_len_id);
		if (_in_id == NULL) {
			status = SGX_ERROR_OUT_OF_MEMORY;
			goto err;
		}

		if (memcpy_s((void*)_in_id, _len_id, _tmp_id, _len_id)) {
			status = SGX_ERROR_UNEXPECTED;
			goto err;
		}

		_in_id[_len_id - 1] = '\0';
		if (_len_id != strlen(_in_id) + 1)
		{
			status = SGX_ERROR_UNEXPECTED;
			goto err;
		}
	}
	if (_tmp_in_buf != NULL && _len_in_buf != 0) {
		_in_in_buf = (char*)malloc(_len_in_buf);
		if (_in_in_buf == NULL) {
			status = SGX_ERROR_OUT_OF_MEMORY;
			goto err;
		}

		if (memcpy_s((void*)_in_in_buf, _len_in_buf, _tmp_in_buf, _len_in_buf)) {
			status = SGX_ERROR_UNEXPECTED;
			goto err;
		}

	}
	if (_tmp_out_buf != NULL && _len_out_buf != 0) {
		if ((_in_out_buf = (char*)malloc(_len_out_buf)) == NULL) {
			status = SGX_ERROR_OUT_OF_MEMORY;
			goto err;
		}

		memset((void*)_in_out_buf, 0, _len_out_buf);
	}

	ms->ms_retval = encrypt((const char*)_in_id, (const char*)_in_in_buf, _tmp_in_buf_len, _in_out_buf, _tmp_out_buf_size);
err:
	if (_in_id) free((void*)_in_id);
	if (_in_in_buf) free((void*)_in_in_buf);
	if (_in_out_buf) {
		if (memcpy_s(_tmp_out_buf, _len_out_buf, _in_out_buf, _len_out_buf)) {
			status = SGX_ERROR_UNEXPECTED;
		}
		free(_in_out_buf);
	}

	return status;
}

static sgx_status_t SGX_CDECL sgx_encrypt_size(void* pms)
{
	CHECK_REF_POINTER(pms, sizeof(ms_encrypt_size_t));
	//
	// fence after pointer checks
	//
	sgx_lfence();
	ms_encrypt_size_t* ms = SGX_CAST(ms_encrypt_size_t*, pms);
	sgx_status_t status = SGX_SUCCESS;
	const char* _tmp_id = ms->ms_id;
	size_t _len_id = ms->ms_id_len ;
	char* _in_id = NULL;

	CHECK_UNIQUE_POINTER(_tmp_id, _len_id);

	//
	// fence after pointer checks
	//
	sgx_lfence();

	if (_tmp_id != NULL && _len_id != 0) {
		_in_id = (char*)malloc(_len_id);
		if (_in_id == NULL) {
			status = SGX_ERROR_OUT_OF_MEMORY;
			goto err;
		}

		if (memcpy_s((void*)_in_id, _len_id, _tmp_id, _len_id)) {
			status = SGX_ERROR_UNEXPECTED;
			goto err;
		}

		_in_id[_len_id - 1] = '\0';
		if (_len_id != strlen(_in_id) + 1)
		{
			status = SGX_ERROR_UNEXPECTED;
			goto err;
		}
	}

	ms->ms_retval = encrypt_size((const char*)_in_id, ms->ms_buf_len);
err:
	if (_in_id) free((void*)_in_id);

	return status;
}

static sgx_status_t SGX_CDECL sgx_encryptex(void* pms)
{
	CHECK_REF_POINTER(pms, sizeof(ms_encryptex_t));
	//
	// fence after pointer checks
	//
	sgx_lfence();
	ms_encryptex_t* ms = SGX_CAST(ms_encryptex_t*, pms);
	sgx_status_t status = SGX_SUCCESS;
	const char* _tmp_id = ms->ms_id;
	size_t _len_id = ms->ms_id_len ;
	char* _in_id = NULL;
	const char* _tmp_in_buf = ms->ms_in_buf;
	int _tmp_in_buf_len = ms->ms_in_buf_len;
	size_t _len_in_buf = _tmp_in_buf_len;
	char* _in_in_buf = NULL;
	const int* _tmp_value_lens = ms->ms_value_lens;
	int _tmp_value_count = ms->ms_value_count;
	size_t _len_value_lens = _tmp_value_count * sizeof(int);
	int* _in_value_lens = NULL;
	const int* _tmp_value_types = ms->ms_value_types;
	size_t _len_value_types = _tmp_value_count * sizeof(int);
	int* _in_value_types = NULL;
	char* _tmp_out_buf = ms->ms_out_buf;
	int _tmp_out_buf_size = ms->ms_out_buf_size;
	size_t _len_out_buf = _tmp_out_buf_size;
	char* _in_out_buf = NULL;
	int* _tmp_out_value_lens = ms->ms_out_value_lens;
	size_t _len_out_value_lens = _tmp_value_count * sizeof(int);
	int* _in_out_value_lens = NULL;

	if (sizeof(*_tmp_value_lens) != 0 &&
		(size_t)_tmp_value_count > (SIZE_MAX / sizeof(*_tmp_value_lens))) {
		return SGX_ERROR_INVALID_PARAMETER;
	}

	if (sizeof(*_tmp_value_types) != 0 &&
		(size_t)_tmp_value_count > (SIZE_MAX / sizeof(*_tmp_value_types))) {
		return SGX_ERROR_INVALID_PARAMETER;
	}

	if (sizeof(*_tmp_out_value_lens) != 0 &&
		(size_t)_tmp_value_count > (SIZE_MAX / sizeof(*_tmp_out_value_lens))) {
		return SGX_ERROR_INVALID_PARAMETER;
	}

	CHECK_UNIQUE_POINTER(_tmp_id, _len_id);
	CHECK_UNIQUE_POINTER(_tmp_in_buf, _len_in_buf);
	CHECK_UNIQUE_POINTER(_tmp_value_lens, _len_value_lens);
	CHECK_UNIQUE_POINTER(_tmp_value_types, _len_value_types);
	CHECK_UNIQUE_POINTER(_tmp_out_buf, _len_out_buf);
	CHECK_UNIQUE_POINTER(_tmp_out_value_lens, _len_out_value_lens);

	//
	// fence after pointer checks
	//
	sgx_lfence();

	if (_tmp_id != NULL && _len_id != 0) {
		_in_id = (char*)malloc(_len_id);
		if (_in_id == NULL) {
			status = SGX_ERROR_OUT_OF_MEMORY;
			goto err;
		}

		if (memcpy_s((void*)_in_id, _len_id, _tmp_id, _len_id)) {
			status = SGX_ERROR_UNEXPECTED;
			goto err;
		}

		_in_id[_len_id - 1] = '\0';
		if (_len_id != strlen(_in_id) + 1)
		{
			status = SGX_ERROR_UNEXPECTED;
			goto err;
		}
	}
	if (_tmp_in_buf != NULL && _len_in_buf != 0) {
		_in_in_buf = (char*)malloc(_len_in_buf);
		if (_in_in_buf == NULL) {
			status = SGX_ERROR_OUT_OF_MEMORY;
			goto err;
		}

		if (memcpy_s((void*)_in_in_buf, _len_in_buf, _tmp_in_buf, _len_in_buf)) {
			status = SGX_ERROR_UNEXPECTED;
			goto err;
		}

	}
	if (_tmp_value_lens != NULL && _len_value_lens != 0) {
		_in_value_lens = (int*)malloc(_len_value_lens);
		if (_in_value_lens == NULL) {
			status = SGX_ERROR_OUT_OF_MEMORY;
			goto err;
		}

		if (memcpy_s((void*)_in_value_lens, _len_value_lens, _tmp_value_lens, _len_value_lens)) {
			status = SGX_ERROR_UNEXPECTED;
			goto err;
		}

	}
	if (_tmp_value_types != NULL && _len_value_types != 0) {
		_in_value_types = (int*)malloc(_len_value_types);
		if (_in_value_types == NULL) {
			status = SGX_ERROR_OUT_OF_MEMORY;
			goto err;
		}

		if (memcpy_s((void*)_in_value_types, _len_value_types, _tmp_value_types, _len_value_types)) {
			status = SGX_ERROR_UNEXPECTED;
			goto err;
		}

	}
	if (_tmp_out_buf != NULL && _len_out_buf != 0) {
		if ((_in_out_buf = (char*)malloc(_len_out_buf)) == NULL) {
			status = SGX_ERROR_OUT_OF_MEMORY;
			goto err;
		}

		memset((void*)_in_out_buf, 0, _len_out_buf);
	}
	if (_tmp_out_value_lens != NULL && _len_out_value_lens != 0) {
		if ((_in_out_value_lens = (int*)malloc(_len_out_value_lens)) == NULL) {
			status = SGX_ERROR_OUT_OF_MEMORY;
			goto err;
		}

		memset((void*)_in_out_value_lens, 0, _len_out_value_lens);
	}

	ms->ms_retval = encryptex((const char*)_in_id, (const char*)_in_in_buf, _tmp_in_buf_len, (const int*)_in_value_lens, (const int*)_in_value_types, _tmp_value_count, _in_out_buf, _tmp_out_buf_size, _in_out_value_lens);
err:
	if (_in_id) free((void*)_in_id);
	if (_in_in_buf) free((void*)_in_in_buf);
	if (_in_value_lens) free((void*)_in_value_lens);
	if (_in_value_types) free((void*)_in_value_types);
	if (_in_out_buf) {
		if (memcpy_s(_tmp_out_buf, _len_out_buf, _in_out_buf, _len_out_buf)) {
			status = SGX_ERROR_UNEXPECTED;
		}
		free(_in_out_buf);
	}
	if (_in_out_value_lens) {
		if (memcpy_s(_tmp_out_value_lens, _len_out_value_lens, _in_out_value_lens, _len_out_value_lens)) {
			status = SGX_ERROR_UNEXPECTED;
		}
		free(_in_out_value_lens);
	}

	return status;
}

static sgx_status_t SGX_CDECL sgx_decrypt(void* pms)
{
	CHECK_REF_POINTER(pms, sizeof(ms_decrypt_t));
	//
	// fence after pointer checks
	//
	sgx_lfence();
	ms_decrypt_t* ms = SGX_CAST(ms_decrypt_t*, pms);
	sgx_status_t status = SGX_SUCCESS;
	const char* _tmp_id = ms->ms_id;
	size_t _len_id = ms->ms_id_len ;
	char* _in_id = NULL;
	const char* _tmp_in_buf = ms->ms_in_buf;
	int _tmp_in_buf_len = ms->ms_in_buf_len;
	size_t _len_in_buf = _tmp_in_buf_len;
	char* _in_in_buf = NULL;
	char* _tmp_out_buf = ms->ms_out_buf;
	int _tmp_out_buf_size = ms->ms_out_buf_size;
	size_t _len_out_buf = _tmp_out_buf_size;
	char* _in_out_buf = NULL;

	CHECK_UNIQUE_POINTER(_tmp_id, _len_id);
	CHECK_UNIQUE_POINTER(_tmp_in_buf, _len_in_buf);
	CHECK_UNIQUE_POINTER(_tmp_out_buf, _len_out_buf);

	//
	// fence after pointer checks
	//
	sgx_lfence();

	if (_tmp_id != NULL && _len_id != 0) {
		_in_id = (char*)malloc(_len_id);
		if (_in_id == NULL) {
			status = SGX_ERROR_OUT_OF_MEMORY;
			goto err;
		}

		if (memcpy_s((void*)_in_id, _len_id, _tmp_id, _len_id)) {
			status = SGX_ERROR_UNEXPECTED;
			goto err;
		}

		_in_id[_len_id - 1] = '\0';
		if (_len_id != strlen(_in_id) + 1)
		{
			status = SGX_ERROR_UNEXPECTED;
			goto err;
		}
	}
	if (_tmp_in_buf != NULL && _len_in_buf != 0) {
		_in_in_buf = (char*)malloc(_len_in_buf);
		if (_in_in_buf == NULL) {
			status = SGX_ERROR_OUT_OF_MEMORY;
			goto err;
		}

		if (memcpy_s((void*)_in_in_buf, _len_in_buf, _tmp_in_buf, _len_in_buf)) {
			status = SGX_ERROR_UNEXPECTED;
			goto err;
		}

	}
	if (_tmp_out_buf != NULL && _len_out_buf != 0) {
		if ((_in_out_buf = (char*)malloc(_len_out_buf)) == NULL) {
			status = SGX_ERROR_OUT_OF_MEMORY;
			goto err;
		}

		memset((void*)_in_out_buf, 0, _len_out_buf);
	}

	ms->ms_retval = decrypt((const char*)_in_id, (const char*)_in_in_buf, _tmp_in_buf_len, _in_out_buf, _tmp_out_buf_size);
err:
	if (_in_id) free((void*)_in_id);
	if (_in_in_buf) free((void*)_in_in_buf);
	if (_in_out_buf) {
		if (memcpy_s(_tmp_out_buf, _len_out_buf, _in_out_buf, _len_out_buf)) {
			status = SGX_ERROR_UNEXPECTED;
		}
		free(_in_out_buf);
	}

	return status;
}

static sgx_status_t SGX_CDECL sgx_public_key_encrypt(void* pms)
{
	CHECK_REF_POINTER(pms, sizeof(ms_public_key_encrypt_t));
	//
	// fence after pointer checks
	//
	sgx_lfence();
	ms_public_key_encrypt_t* ms = SGX_CAST(ms_public_key_encrypt_t*, pms);
	sgx_status_t status = SGX_SUCCESS;
	const char* _tmp_id = ms->ms_id;
	size_t _len_id = ms->ms_id_len ;
	char* _in_id = NULL;
	const char* _tmp_in_buf = ms->ms_in_buf;
	int _tmp_in_buf_len = ms->ms_in_buf_len;
	size_t _len_in_buf = _tmp_in_buf_len;
	char* _in_in_buf = NULL;
	char* _tmp_out_buf = ms->ms_out_buf;
	int _tmp_out_buf_size = ms->ms_out_buf_size;
	size_t _len_out_buf = _tmp_out_buf_size;
	char* _in_out_buf = NULL;

	CHECK_UNIQUE_POINTER(_tmp_id, _len_id);
	CHECK_UNIQUE_POINTER(_tmp_in_buf, _len_in_buf);
	CHECK_UNIQUE_POINTER(_tmp_out_buf, _len_out_buf);

	//
	// fence after pointer checks
	//
	sgx_lfence();

	if (_tmp_id != NULL && _len_id != 0) {
		_in_id = (char*)malloc(_len_id);
		if (_in_id == NULL) {
			status = SGX_ERROR_OUT_OF_MEMORY;
			goto err;
		}

		if (memcpy_s((void*)_in_id, _len_id, _tmp_id, _len_id)) {
			status = SGX_ERROR_UNEXPECTED;
			goto err;
		}

		_in_id[_len_id - 1] = '\0';
		if (_len_id != strlen(_in_id) + 1)
		{
			status = SGX_ERROR_UNEXPECTED;
			goto err;
		}
	}
	if (_tmp_in_buf != NULL && _len_in_buf != 0) {
		_in_in_buf = (char*)malloc(_len_in_buf);
		if (_in_in_buf == NULL) {
			status = SGX_ERROR_OUT_OF_MEMORY;
			goto err;
		}

		if (memcpy_s((void*)_in_in_buf, _len_in_buf, _tmp_in_buf, _len_in_buf)) {
			status = SGX_ERROR_UNEXPECTED;
			goto err;
		}

	}
	if (_tmp_out_buf != NULL && _len_out_buf != 0) {
		if ((_in_out_buf = (char*)malloc(_len_out_buf)) == NULL) {
			status = SGX_ERROR_OUT_OF_MEMORY;
			goto err;
		}

		memset((void*)_in_out_buf, 0, _len_out_buf);
	}

	ms->ms_retval = public_key_encrypt((const char*)_in_id, (const char*)_in_in_buf, _tmp_in_buf_len, _in_out_buf, _tmp_out_buf_size);
err:
	if (_in_id) free((void*)_in_id);
	if (_in_in_buf) free((void*)_in_in_buf);
	if (_in_out_buf) {
		if (memcpy_s(_tmp_out_buf, _len_out_buf, _in_out_buf, _len_out_buf)) {
			status = SGX_ERROR_UNEXPECTED;
		}
		free(_in_out_buf);
	}

	return status;
}

static sgx_status_t SGX_CDECL sgx_private_key_decrypt(void* pms)
{
	CHECK_REF_POINTER(pms, sizeof(ms_private_key_decrypt_t));
	//
	// fence after pointer checks
	//
	sgx_lfence();
	ms_private_key_decrypt_t* ms = SGX_CAST(ms_private_key_decrypt_t*, pms);
	sgx_status_t status = SGX_SUCCESS;
	const char* _tmp_id = ms->ms_id;
	size_t _len_id = ms->ms_id_len ;
	char* _in_id = NULL;
	const char* _tmp_in_buf = ms->ms_in_buf;
	int _tmp_in_buf_len = ms->ms_in_buf_len;
	size_t _len_in_buf = _tmp_in_buf_len;
	char* _in_in_buf = NULL;
	char* _tmp_out_buf = ms->ms_out_buf;
	int _tmp_out_buf_size = ms->ms_out_buf_size;
	size_t _len_out_buf = _tmp_out_buf_size;
	char* _in_out_buf = NULL;

	CHECK_UNIQUE_POINTER(_tmp_id, _len_id);
	CHECK_UNIQUE_POINTER(_tmp_in_buf, _len_in_buf);
	CHECK_UNIQUE_POINTER(_tmp_out_buf, _len_out_buf);

	//
	// fence after pointer checks
	//
	sgx_lfence();

	if (_tmp_id != NULL && _len_id != 0) {
		_in_id = (char*)malloc(_len_id);
		if (_in_id == NULL) {
			status = SGX_ERROR_OUT_OF_MEMORY;
			goto err;
		}

		if (memcpy_s((void*)_in_id, _len_id, _tmp_id, _len_id)) {
			status = SGX_ERROR_UNEXPECTED;
			goto err;
		}

		_in_id[_len_id - 1] = '\0';
		if (_len_id != strlen(_in_id) + 1)
		{
			status = SGX_ERROR_UNEXPECTED;
			goto err;
		}
	}
	if (_tmp_in_buf != NULL && _len_in_buf != 0) {
		_in_in_buf = (char*)malloc(_len_in_buf);
		if (_in_in_buf == NULL) {
			status = SGX_ERROR_OUT_OF_MEMORY;
			goto err;
		}

		if (memcpy_s((void*)_in_in_buf, _len_in_buf, _tmp_in_buf, _len_in_buf)) {
			status = SGX_ERROR_UNEXPECTED;
			goto err;
		}

	}
	if (_tmp_out_buf != NULL && _len_out_buf != 0) {
		if ((_in_out_buf = (char*)malloc(_len_out_buf)) == NULL) {
			status = SGX_ERROR_OUT_OF_MEMORY;
			goto err;
		}

		memset((void*)_in_out_buf, 0, _len_out_buf);
	}

	ms->ms_retval = private_key_decrypt((const char*)_in_id, (const char*)_in_in_buf, _tmp_in_buf_len, _in_out_buf, _tmp_out_buf_size);
err:
	if (_in_id) free((void*)_in_id);
	if (_in_in_buf) free((void*)_in_in_buf);
	if (_in_out_buf) {
		if (memcpy_s(_tmp_out_buf, _len_out_buf, _in_out_buf, _len_out_buf)) {
			status = SGX_ERROR_UNEXPECTED;
		}
		free(_in_out_buf);
	}

	return status;
}

static sgx_status_t SGX_CDECL sgx_private_key_encrypt(void* pms)
{
	CHECK_REF_POINTER(pms, sizeof(ms_private_key_encrypt_t));
	//
	// fence after pointer checks
	//
	sgx_lfence();
	ms_private_key_encrypt_t* ms = SGX_CAST(ms_private_key_encrypt_t*, pms);
	sgx_status_t status = SGX_SUCCESS;
	const char* _tmp_id = ms->ms_id;
	size_t _len_id = ms->ms_id_len ;
	char* _in_id = NULL;
	const char* _tmp_in_buf = ms->ms_in_buf;
	int _tmp_in_buf_len = ms->ms_in_buf_len;
	size_t _len_in_buf = _tmp_in_buf_len;
	char* _in_in_buf = NULL;
	char* _tmp_out_buf = ms->ms_out_buf;
	int _tmp_out_buf_size = ms->ms_out_buf_size;
	size_t _len_out_buf = _tmp_out_buf_size;
	char* _in_out_buf = NULL;

	CHECK_UNIQUE_POINTER(_tmp_id, _len_id);
	CHECK_UNIQUE_POINTER(_tmp_in_buf, _len_in_buf);
	CHECK_UNIQUE_POINTER(_tmp_out_buf, _len_out_buf);

	//
	// fence after pointer checks
	//
	sgx_lfence();

	if (_tmp_id != NULL && _len_id != 0) {
		_in_id = (char*)malloc(_len_id);
		if (_in_id == NULL) {
			status = SGX_ERROR_OUT_OF_MEMORY;
			goto err;
		}

		if (memcpy_s((void*)_in_id, _len_id, _tmp_id, _len_id)) {
			status = SGX_ERROR_UNEXPECTED;
			goto err;
		}

		_in_id[_len_id - 1] = '\0';
		if (_len_id != strlen(_in_id) + 1)
		{
			status = SGX_ERROR_UNEXPECTED;
			goto err;
		}
	}
	if (_tmp_in_buf != NULL && _len_in_buf != 0) {
		_in_in_buf = (char*)malloc(_len_in_buf);
		if (_in_in_buf == NULL) {
			status = SGX_ERROR_OUT_OF_MEMORY;
			goto err;
		}

		if (memcpy_s((void*)_in_in_buf, _len_in_buf, _tmp_in_buf, _len_in_buf)) {
			status = SGX_ERROR_UNEXPECTED;
			goto err;
		}

	}
	if (_tmp_out_buf != NULL && _len_out_buf != 0) {
		if ((_in_out_buf = (char*)malloc(_len_out_buf)) == NULL) {
			status = SGX_ERROR_OUT_OF_MEMORY;
			goto err;
		}

		memset((void*)_in_out_buf, 0, _len_out_buf);
	}

	ms->ms_retval = private_key_encrypt((const char*)_in_id, (const char*)_in_in_buf, _tmp_in_buf_len, _in_out_buf, _tmp_out_buf_size);
err:
	if (_in_id) free((void*)_in_id);
	if (_in_in_buf) free((void*)_in_in_buf);
	if (_in_out_buf) {
		if (memcpy_s(_tmp_out_buf, _len_out_buf, _in_out_buf, _len_out_buf)) {
			status = SGX_ERROR_UNEXPECTED;
		}
		free(_in_out_buf);
	}

	return status;
}

static sgx_status_t SGX_CDECL sgx_public_key_decrypt(void* pms)
{
	CHECK_REF_POINTER(pms, sizeof(ms_public_key_decrypt_t));
	//
	// fence after pointer checks
	//
	sgx_lfence();
	ms_public_key_decrypt_t* ms = SGX_CAST(ms_public_key_decrypt_t*, pms);
	sgx_status_t status = SGX_SUCCESS;
	const char* _tmp_id = ms->ms_id;
	size_t _len_id = ms->ms_id_len ;
	char* _in_id = NULL;
	const char* _tmp_in_buf = ms->ms_in_buf;
	int _tmp_in_buf_len = ms->ms_in_buf_len;
	size_t _len_in_buf = _tmp_in_buf_len;
	char* _in_in_buf = NULL;
	char* _tmp_out_buf = ms->ms_out_buf;
	int _tmp_out_buf_size = ms->ms_out_buf_size;
	size_t _len_out_buf = _tmp_out_buf_size;
	char* _in_out_buf = NULL;

	CHECK_UNIQUE_POINTER(_tmp_id, _len_id);
	CHECK_UNIQUE_POINTER(_tmp_in_buf, _len_in_buf);
	CHECK_UNIQUE_POINTER(_tmp_out_buf, _len_out_buf);

	//
	// fence after pointer checks
	//
	sgx_lfence();

	if (_tmp_id != NULL && _len_id != 0) {
		_in_id = (char*)malloc(_len_id);
		if (_in_id == NULL) {
			status = SGX_ERROR_OUT_OF_MEMORY;
			goto err;
		}

		if (memcpy_s((void*)_in_id, _len_id, _tmp_id, _len_id)) {
			status = SGX_ERROR_UNEXPECTED;
			goto err;
		}

		_in_id[_len_id - 1] = '\0';
		if (_len_id != strlen(_in_id) + 1)
		{
			status = SGX_ERROR_UNEXPECTED;
			goto err;
		}
	}
	if (_tmp_in_buf != NULL && _len_in_buf != 0) {
		_in_in_buf = (char*)malloc(_len_in_buf);
		if (_in_in_buf == NULL) {
			status = SGX_ERROR_OUT_OF_MEMORY;
			goto err;
		}

		if (memcpy_s((void*)_in_in_buf, _len_in_buf, _tmp_in_buf, _len_in_buf)) {
			status = SGX_ERROR_UNEXPECTED;
			goto err;
		}

	}
	if (_tmp_out_buf != NULL && _len_out_buf != 0) {
		if ((_in_out_buf = (char*)malloc(_len_out_buf)) == NULL) {
			status = SGX_ERROR_OUT_OF_MEMORY;
			goto err;
		}

		memset((void*)_in_out_buf, 0, _len_out_buf);
	}

	ms->ms_retval = public_key_decrypt((const char*)_in_id, (const char*)_in_in_buf, _tmp_in_buf_len, _in_out_buf, _tmp_out_buf_size);
err:
	if (_in_id) free((void*)_in_id);
	if (_in_in_buf) free((void*)_in_in_buf);
	if (_in_out_buf) {
		if (memcpy_s(_tmp_out_buf, _len_out_buf, _in_out_buf, _len_out_buf)) {
			status = SGX_ERROR_UNEXPECTED;
		}
		free(_in_out_buf);
	}

	return status;
}

static sgx_status_t SGX_CDECL sgx_sign(void* pms)
{
	CHECK_REF_POINTER(pms, sizeof(ms_sign_t));
	//
	// fence after pointer checks
	//
	sgx_lfence();
	ms_sign_t* ms = SGX_CAST(ms_sign_t*, pms);
	sgx_status_t status = SGX_SUCCESS;
	const char* _tmp_id = ms->ms_id;
	size_t _len_id = ms->ms_id_len ;
	char* _in_id = NULL;
	const char* _tmp_in_buf = ms->ms_in_buf;
	int _tmp_in_buf_len = ms->ms_in_buf_len;
	size_t _len_in_buf = _tmp_in_buf_len;
	char* _in_in_buf = NULL;
	char* _tmp_out_buf = ms->ms_out_buf;
	int _tmp_out_buf_size = ms->ms_out_buf_size;
	size_t _len_out_buf = _tmp_out_buf_size;
	char* _in_out_buf = NULL;

	CHECK_UNIQUE_POINTER(_tmp_id, _len_id);
	CHECK_UNIQUE_POINTER(_tmp_in_buf, _len_in_buf);
	CHECK_UNIQUE_POINTER(_tmp_out_buf, _len_out_buf);

	//
	// fence after pointer checks
	//
	sgx_lfence();

	if (_tmp_id != NULL && _len_id != 0) {
		_in_id = (char*)malloc(_len_id);
		if (_in_id == NULL) {
			status = SGX_ERROR_OUT_OF_MEMORY;
			goto err;
		}

		if (memcpy_s((void*)_in_id, _len_id, _tmp_id, _len_id)) {
			status = SGX_ERROR_UNEXPECTED;
			goto err;
		}

		_in_id[_len_id - 1] = '\0';
		if (_len_id != strlen(_in_id) + 1)
		{
			status = SGX_ERROR_UNEXPECTED;
			goto err;
		}
	}
	if (_tmp_in_buf != NULL && _len_in_buf != 0) {
		_in_in_buf = (char*)malloc(_len_in_buf);
		if (_in_in_buf == NULL) {
			status = SGX_ERROR_OUT_OF_MEMORY;
			goto err;
		}

		if (memcpy_s((void*)_in_in_buf, _len_in_buf, _tmp_in_buf, _len_in_buf)) {
			status = SGX_ERROR_UNEXPECTED;
			goto err;
		}

	}
	if (_tmp_out_buf != NULL && _len_out_buf != 0) {
		if ((_in_out_buf = (char*)malloc(_len_out_buf)) == NULL) {
			status = SGX_ERROR_OUT_OF_MEMORY;
			goto err;
		}

		memset((void*)_in_out_buf, 0, _len_out_buf);
	}

	ms->ms_retval = sign((const char*)_in_id, (const char*)_in_in_buf, _tmp_in_buf_len, _in_out_buf, _tmp_out_buf_size);
err:
	if (_in_id) free((void*)_in_id);
	if (_in_in_buf) free((void*)_in_in_buf);
	if (_in_out_buf) {
		if (memcpy_s(_tmp_out_buf, _len_out_buf, _in_out_buf, _len_out_buf)) {
			status = SGX_ERROR_UNEXPECTED;
		}
		free(_in_out_buf);
	}

	return status;
}

static sgx_status_t SGX_CDECL sgx_sha256_encrytp(void* pms)
{
	CHECK_REF_POINTER(pms, sizeof(ms_sha256_encrytp_t));
	//
	// fence after pointer checks
	//
	sgx_lfence();
	ms_sha256_encrytp_t* ms = SGX_CAST(ms_sha256_encrytp_t*, pms);
	sgx_status_t status = SGX_SUCCESS;
	const char* _tmp_id = ms->ms_id;
	size_t _len_id = ms->ms_id_len ;
	char* _in_id = NULL;
	const char* _tmp_in_buf = ms->ms_in_buf;
	int _tmp_in_buf_len = ms->ms_in_buf_len;
	size_t _len_in_buf = _tmp_in_buf_len;
	char* _in_in_buf = NULL;
	char* _tmp_out_buf = ms->ms_out_buf;
	int _tmp_out_buf_size = ms->ms_out_buf_size;
	size_t _len_out_buf = _tmp_out_buf_size;
	char* _in_out_buf = NULL;

	CHECK_UNIQUE_POINTER(_tmp_id, _len_id);
	CHECK_UNIQUE_POINTER(_tmp_in_buf, _len_in_buf);
	CHECK_UNIQUE_POINTER(_tmp_out_buf, _len_out_buf);

	//
	// fence after pointer checks
	//
	sgx_lfence();

	if (_tmp_id != NULL && _len_id != 0) {
		_in_id = (char*)malloc(_len_id);
		if (_in_id == NULL) {
			status = SGX_ERROR_OUT_OF_MEMORY;
			goto err;
		}

		if (memcpy_s((void*)_in_id, _len_id, _tmp_id, _len_id)) {
			status = SGX_ERROR_UNEXPECTED;
			goto err;
		}

		_in_id[_len_id - 1] = '\0';
		if (_len_id != strlen(_in_id) + 1)
		{
			status = SGX_ERROR_UNEXPECTED;
			goto err;
		}
	}
	if (_tmp_in_buf != NULL && _len_in_buf != 0) {
		_in_in_buf = (char*)malloc(_len_in_buf);
		if (_in_in_buf == NULL) {
			status = SGX_ERROR_OUT_OF_MEMORY;
			goto err;
		}

		if (memcpy_s((void*)_in_in_buf, _len_in_buf, _tmp_in_buf, _len_in_buf)) {
			status = SGX_ERROR_UNEXPECTED;
			goto err;
		}

	}
	if (_tmp_out_buf != NULL && _len_out_buf != 0) {
		if ((_in_out_buf = (char*)malloc(_len_out_buf)) == NULL) {
			status = SGX_ERROR_OUT_OF_MEMORY;
			goto err;
		}

		memset((void*)_in_out_buf, 0, _len_out_buf);
	}

	ms->ms_retval = sha256_encrytp((const char*)_in_id, (const char*)_in_in_buf, _tmp_in_buf_len, _in_out_buf, _tmp_out_buf_size);
err:
	if (_in_id) free((void*)_in_id);
	if (_in_in_buf) free((void*)_in_in_buf);
	if (_in_out_buf) {
		if (memcpy_s(_tmp_out_buf, _len_out_buf, _in_out_buf, _len_out_buf)) {
			status = SGX_ERROR_UNEXPECTED;
		}
		free(_in_out_buf);
	}

	return status;
}

static sgx_status_t SGX_CDECL sgx_crypto_key(void* pms)
{
	CHECK_REF_POINTER(pms, sizeof(ms_crypto_key_t));
	//
	// fence after pointer checks
	//
	sgx_lfence();
	ms_crypto_key_t* ms = SGX_CAST(ms_crypto_key_t*, pms);
	sgx_status_t status = SGX_SUCCESS;
	const char* _tmp_id = ms->ms_id;
	size_t _len_id = ms->ms_id_len ;
	char* _in_id = NULL;
	char* _tmp_key = ms->ms_key;
	int _tmp_key_len = ms->ms_key_len;
	size_t _len_key = _tmp_key_len;
	char* _in_key = NULL;

	CHECK_UNIQUE_POINTER(_tmp_id, _len_id);
	CHECK_UNIQUE_POINTER(_tmp_key, _len_key);

	//
	// fence after pointer checks
	//
	sgx_lfence();

	if (_tmp_id != NULL && _len_id != 0) {
		_in_id = (char*)malloc(_len_id);
		if (_in_id == NULL) {
			status = SGX_ERROR_OUT_OF_MEMORY;
			goto err;
		}

		if (memcpy_s((void*)_in_id, _len_id, _tmp_id, _len_id)) {
			status = SGX_ERROR_UNEXPECTED;
			goto err;
		}

		_in_id[_len_id - 1] = '\0';
		if (_len_id != strlen(_in_id) + 1)
		{
			status = SGX_ERROR_UNEXPECTED;
			goto err;
		}
	}
	if (_tmp_key != NULL && _len_key != 0) {
		if ((_in_key = (char*)malloc(_len_key)) == NULL) {
			status = SGX_ERROR_OUT_OF_MEMORY;
			goto err;
		}

		memset((void*)_in_key, 0, _len_key);
	}

	ms->ms_retval = crypto_key((const char*)_in_id, _in_key, _tmp_key_len);
err:
	if (_in_id) free((void*)_in_id);
	if (_in_key) {
		if (memcpy_s(_tmp_key, _len_key, _in_key, _len_key)) {
			status = SGX_ERROR_UNEXPECTED;
		}
		free(_in_key);
	}

	return status;
}

SGX_EXTERNC const struct {
	size_t nr_ecall;
	struct {void* call_addr; uint8_t is_priv;} ecall_table[13];
} g_ecall_table = {
	13,
	{
		{(void*)(uintptr_t)sgx_initVault, 0},
		{(void*)(uintptr_t)sgx_uninitVault, 0},
		{(void*)(uintptr_t)sgx_encrypt, 0},
		{(void*)(uintptr_t)sgx_encrypt_size, 0},
		{(void*)(uintptr_t)sgx_encryptex, 0},
		{(void*)(uintptr_t)sgx_decrypt, 0},
		{(void*)(uintptr_t)sgx_public_key_encrypt, 0},
		{(void*)(uintptr_t)sgx_private_key_decrypt, 0},
		{(void*)(uintptr_t)sgx_private_key_encrypt, 0},
		{(void*)(uintptr_t)sgx_public_key_decrypt, 0},
		{(void*)(uintptr_t)sgx_sign, 0},
		{(void*)(uintptr_t)sgx_sha256_encrytp, 0},
		{(void*)(uintptr_t)sgx_crypto_key, 0},
	}
};

SGX_EXTERNC const struct {
	size_t nr_ocall;
	uint8_t entry_table[21][13];
} g_dyn_entry_table = {
	21,
	{
		{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
		{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
		{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
		{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
		{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
		{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
		{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
		{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
		{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
		{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
		{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
		{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
		{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
		{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
		{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
		{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
		{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
		{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
		{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
		{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
		{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
	}
};


sgx_status_t SGX_CDECL sgx_oc_cpuidex(int cpuinfo[4], int leaf, int subleaf)
{
	sgx_status_t status = SGX_SUCCESS;
	size_t _len_cpuinfo = 4 * sizeof(int);

	ms_sgx_oc_cpuidex_t* ms = NULL;
	size_t ocalloc_size = sizeof(ms_sgx_oc_cpuidex_t);
	void *__tmp = NULL;

	void *__tmp_cpuinfo = NULL;

	CHECK_ENCLAVE_POINTER(cpuinfo, _len_cpuinfo);

	ocalloc_size += (cpuinfo != NULL) ? _len_cpuinfo : 0;

	__tmp = sgx_ocalloc(ocalloc_size);
	if (__tmp == NULL) {
		sgx_ocfree();
		return SGX_ERROR_UNEXPECTED;
	}
	ms = (ms_sgx_oc_cpuidex_t*)__tmp;
	__tmp = (void *)((size_t)__tmp + sizeof(ms_sgx_oc_cpuidex_t));
	ocalloc_size -= sizeof(ms_sgx_oc_cpuidex_t);

	if (cpuinfo != NULL) {
		ms->ms_cpuinfo = (int*)__tmp;
		__tmp_cpuinfo = __tmp;
		memset(__tmp_cpuinfo, 0, _len_cpuinfo);
		__tmp = (void *)((size_t)__tmp + _len_cpuinfo);
		ocalloc_size -= _len_cpuinfo;
	} else {
		ms->ms_cpuinfo = NULL;
	}
	
	ms->ms_leaf = leaf;
	ms->ms_subleaf = subleaf;
	status = sgx_ocall(0, ms);

	if (status == SGX_SUCCESS) {
		if (cpuinfo) {
			if (memcpy_s((void*)cpuinfo, _len_cpuinfo, __tmp_cpuinfo, _len_cpuinfo)) {
				sgx_ocfree();
				return SGX_ERROR_UNEXPECTED;
			}
		}
	}
	sgx_ocfree();
	return status;
}

sgx_status_t SGX_CDECL sgx_thread_wait_untrusted_event_ocall(int* retval, const void* self)
{
	sgx_status_t status = SGX_SUCCESS;

	ms_sgx_thread_wait_untrusted_event_ocall_t* ms = NULL;
	size_t ocalloc_size = sizeof(ms_sgx_thread_wait_untrusted_event_ocall_t);
	void *__tmp = NULL;


	__tmp = sgx_ocalloc(ocalloc_size);
	if (__tmp == NULL) {
		sgx_ocfree();
		return SGX_ERROR_UNEXPECTED;
	}
	ms = (ms_sgx_thread_wait_untrusted_event_ocall_t*)__tmp;
	__tmp = (void *)((size_t)__tmp + sizeof(ms_sgx_thread_wait_untrusted_event_ocall_t));
	ocalloc_size -= sizeof(ms_sgx_thread_wait_untrusted_event_ocall_t);

	ms->ms_self = self;
	status = sgx_ocall(1, ms);

	if (status == SGX_SUCCESS) {
		if (retval) *retval = ms->ms_retval;
	}
	sgx_ocfree();
	return status;
}

sgx_status_t SGX_CDECL sgx_thread_set_untrusted_event_ocall(int* retval, const void* waiter)
{
	sgx_status_t status = SGX_SUCCESS;

	ms_sgx_thread_set_untrusted_event_ocall_t* ms = NULL;
	size_t ocalloc_size = sizeof(ms_sgx_thread_set_untrusted_event_ocall_t);
	void *__tmp = NULL;


	__tmp = sgx_ocalloc(ocalloc_size);
	if (__tmp == NULL) {
		sgx_ocfree();
		return SGX_ERROR_UNEXPECTED;
	}
	ms = (ms_sgx_thread_set_untrusted_event_ocall_t*)__tmp;
	__tmp = (void *)((size_t)__tmp + sizeof(ms_sgx_thread_set_untrusted_event_ocall_t));
	ocalloc_size -= sizeof(ms_sgx_thread_set_untrusted_event_ocall_t);

	ms->ms_waiter = waiter;
	status = sgx_ocall(2, ms);

	if (status == SGX_SUCCESS) {
		if (retval) *retval = ms->ms_retval;
	}
	sgx_ocfree();
	return status;
}

sgx_status_t SGX_CDECL sgx_thread_setwait_untrusted_events_ocall(int* retval, const void* waiter, const void* self)
{
	sgx_status_t status = SGX_SUCCESS;

	ms_sgx_thread_setwait_untrusted_events_ocall_t* ms = NULL;
	size_t ocalloc_size = sizeof(ms_sgx_thread_setwait_untrusted_events_ocall_t);
	void *__tmp = NULL;


	__tmp = sgx_ocalloc(ocalloc_size);
	if (__tmp == NULL) {
		sgx_ocfree();
		return SGX_ERROR_UNEXPECTED;
	}
	ms = (ms_sgx_thread_setwait_untrusted_events_ocall_t*)__tmp;
	__tmp = (void *)((size_t)__tmp + sizeof(ms_sgx_thread_setwait_untrusted_events_ocall_t));
	ocalloc_size -= sizeof(ms_sgx_thread_setwait_untrusted_events_ocall_t);

	ms->ms_waiter = waiter;
	ms->ms_self = self;
	status = sgx_ocall(3, ms);

	if (status == SGX_SUCCESS) {
		if (retval) *retval = ms->ms_retval;
	}
	sgx_ocfree();
	return status;
}

sgx_status_t SGX_CDECL sgx_thread_set_multiple_untrusted_events_ocall(int* retval, const void** waiters, size_t total)
{
	sgx_status_t status = SGX_SUCCESS;
	size_t _len_waiters = total * sizeof(void*);

	ms_sgx_thread_set_multiple_untrusted_events_ocall_t* ms = NULL;
	size_t ocalloc_size = sizeof(ms_sgx_thread_set_multiple_untrusted_events_ocall_t);
	void *__tmp = NULL;


	CHECK_ENCLAVE_POINTER(waiters, _len_waiters);

	ocalloc_size += (waiters != NULL) ? _len_waiters : 0;

	__tmp = sgx_ocalloc(ocalloc_size);
	if (__tmp == NULL) {
		sgx_ocfree();
		return SGX_ERROR_UNEXPECTED;
	}
	ms = (ms_sgx_thread_set_multiple_untrusted_events_ocall_t*)__tmp;
	__tmp = (void *)((size_t)__tmp + sizeof(ms_sgx_thread_set_multiple_untrusted_events_ocall_t));
	ocalloc_size -= sizeof(ms_sgx_thread_set_multiple_untrusted_events_ocall_t);

	if (waiters != NULL) {
		ms->ms_waiters = (const void**)__tmp;
		if (memcpy_s(__tmp, ocalloc_size, waiters, _len_waiters)) {
			sgx_ocfree();
			return SGX_ERROR_UNEXPECTED;
		}
		__tmp = (void *)((size_t)__tmp + _len_waiters);
		ocalloc_size -= _len_waiters;
	} else {
		ms->ms_waiters = NULL;
	}
	
	ms->ms_total = total;
	status = sgx_ocall(4, ms);

	if (status == SGX_SUCCESS) {
		if (retval) *retval = ms->ms_retval;
	}
	sgx_ocfree();
	return status;
}

sgx_status_t SGX_CDECL ocall_get_string(char* buf, int len)
{
	sgx_status_t status = SGX_SUCCESS;
	size_t _len_buf = len;

	ms_ocall_get_string_t* ms = NULL;
	size_t ocalloc_size = sizeof(ms_ocall_get_string_t);
	void *__tmp = NULL;

	void *__tmp_buf = NULL;

	CHECK_ENCLAVE_POINTER(buf, _len_buf);

	ocalloc_size += (buf != NULL) ? _len_buf : 0;

	__tmp = sgx_ocalloc(ocalloc_size);
	if (__tmp == NULL) {
		sgx_ocfree();
		return SGX_ERROR_UNEXPECTED;
	}
	ms = (ms_ocall_get_string_t*)__tmp;
	__tmp = (void *)((size_t)__tmp + sizeof(ms_ocall_get_string_t));
	ocalloc_size -= sizeof(ms_ocall_get_string_t);

	if (buf != NULL) {
		ms->ms_buf = (char*)__tmp;
		__tmp_buf = __tmp;
		memset(__tmp_buf, 0, _len_buf);
		__tmp = (void *)((size_t)__tmp + _len_buf);
		ocalloc_size -= _len_buf;
	} else {
		ms->ms_buf = NULL;
	}
	
	ms->ms_len = len;
	status = sgx_ocall(5, ms);

	if (status == SGX_SUCCESS) {
		if (buf) {
			if (memcpy_s((void*)buf, _len_buf, __tmp_buf, _len_buf)) {
				sgx_ocfree();
				return SGX_ERROR_UNEXPECTED;
			}
		}
	}
	sgx_ocfree();
	return status;
}

sgx_status_t SGX_CDECL ocall_print_string(const char* string)
{
	sgx_status_t status = SGX_SUCCESS;
	size_t _len_string = string ? strlen(string) + 1 : 0;

	ms_ocall_print_string_t* ms = NULL;
	size_t ocalloc_size = sizeof(ms_ocall_print_string_t);
	void *__tmp = NULL;


	CHECK_ENCLAVE_POINTER(string, _len_string);

	ocalloc_size += (string != NULL) ? _len_string : 0;

	__tmp = sgx_ocalloc(ocalloc_size);
	if (__tmp == NULL) {
		sgx_ocfree();
		return SGX_ERROR_UNEXPECTED;
	}
	ms = (ms_ocall_print_string_t*)__tmp;
	__tmp = (void *)((size_t)__tmp + sizeof(ms_ocall_print_string_t));
	ocalloc_size -= sizeof(ms_ocall_print_string_t);

	if (string != NULL) {
		ms->ms_string = (const char*)__tmp;
		if (memcpy_s(__tmp, ocalloc_size, string, _len_string)) {
			sgx_ocfree();
			return SGX_ERROR_UNEXPECTED;
		}
		__tmp = (void *)((size_t)__tmp + _len_string);
		ocalloc_size -= _len_string;
	} else {
		ms->ms_string = NULL;
	}
	
	status = sgx_ocall(6, ms);

	if (status == SGX_SUCCESS) {
	}
	sgx_ocfree();
	return status;
}

sgx_status_t SGX_CDECL ocall_log_info(const char* buf)
{
	sgx_status_t status = SGX_SUCCESS;
	size_t _len_buf = buf ? strlen(buf) + 1 : 0;

	ms_ocall_log_info_t* ms = NULL;
	size_t ocalloc_size = sizeof(ms_ocall_log_info_t);
	void *__tmp = NULL;


	CHECK_ENCLAVE_POINTER(buf, _len_buf);

	ocalloc_size += (buf != NULL) ? _len_buf : 0;

	__tmp = sgx_ocalloc(ocalloc_size);
	if (__tmp == NULL) {
		sgx_ocfree();
		return SGX_ERROR_UNEXPECTED;
	}
	ms = (ms_ocall_log_info_t*)__tmp;
	__tmp = (void *)((size_t)__tmp + sizeof(ms_ocall_log_info_t));
	ocalloc_size -= sizeof(ms_ocall_log_info_t);

	if (buf != NULL) {
		ms->ms_buf = (const char*)__tmp;
		if (memcpy_s(__tmp, ocalloc_size, buf, _len_buf)) {
			sgx_ocfree();
			return SGX_ERROR_UNEXPECTED;
		}
		__tmp = (void *)((size_t)__tmp + _len_buf);
		ocalloc_size -= _len_buf;
	} else {
		ms->ms_buf = NULL;
	}
	
	status = sgx_ocall(7, ms);

	if (status == SGX_SUCCESS) {
	}
	sgx_ocfree();
	return status;
}

sgx_status_t SGX_CDECL ocall_log_warning(const char* buf)
{
	sgx_status_t status = SGX_SUCCESS;
	size_t _len_buf = buf ? strlen(buf) + 1 : 0;

	ms_ocall_log_warning_t* ms = NULL;
	size_t ocalloc_size = sizeof(ms_ocall_log_warning_t);
	void *__tmp = NULL;


	CHECK_ENCLAVE_POINTER(buf, _len_buf);

	ocalloc_size += (buf != NULL) ? _len_buf : 0;

	__tmp = sgx_ocalloc(ocalloc_size);
	if (__tmp == NULL) {
		sgx_ocfree();
		return SGX_ERROR_UNEXPECTED;
	}
	ms = (ms_ocall_log_warning_t*)__tmp;
	__tmp = (void *)((size_t)__tmp + sizeof(ms_ocall_log_warning_t));
	ocalloc_size -= sizeof(ms_ocall_log_warning_t);

	if (buf != NULL) {
		ms->ms_buf = (const char*)__tmp;
		if (memcpy_s(__tmp, ocalloc_size, buf, _len_buf)) {
			sgx_ocfree();
			return SGX_ERROR_UNEXPECTED;
		}
		__tmp = (void *)((size_t)__tmp + _len_buf);
		ocalloc_size -= _len_buf;
	} else {
		ms->ms_buf = NULL;
	}
	
	status = sgx_ocall(8, ms);

	if (status == SGX_SUCCESS) {
	}
	sgx_ocfree();
	return status;
}

sgx_status_t SGX_CDECL ocall_log_error(const char* buf)
{
	sgx_status_t status = SGX_SUCCESS;
	size_t _len_buf = buf ? strlen(buf) + 1 : 0;

	ms_ocall_log_error_t* ms = NULL;
	size_t ocalloc_size = sizeof(ms_ocall_log_error_t);
	void *__tmp = NULL;


	CHECK_ENCLAVE_POINTER(buf, _len_buf);

	ocalloc_size += (buf != NULL) ? _len_buf : 0;

	__tmp = sgx_ocalloc(ocalloc_size);
	if (__tmp == NULL) {
		sgx_ocfree();
		return SGX_ERROR_UNEXPECTED;
	}
	ms = (ms_ocall_log_error_t*)__tmp;
	__tmp = (void *)((size_t)__tmp + sizeof(ms_ocall_log_error_t));
	ocalloc_size -= sizeof(ms_ocall_log_error_t);

	if (buf != NULL) {
		ms->ms_buf = (const char*)__tmp;
		if (memcpy_s(__tmp, ocalloc_size, buf, _len_buf)) {
			sgx_ocfree();
			return SGX_ERROR_UNEXPECTED;
		}
		__tmp = (void *)((size_t)__tmp + _len_buf);
		ocalloc_size -= _len_buf;
	} else {
		ms->ms_buf = NULL;
	}
	
	status = sgx_ocall(9, ms);

	if (status == SGX_SUCCESS) {
	}
	sgx_ocfree();
	return status;
}

sgx_status_t SGX_CDECL ocall_log_fatal(const char* buf)
{
	sgx_status_t status = SGX_SUCCESS;
	size_t _len_buf = buf ? strlen(buf) + 1 : 0;

	ms_ocall_log_fatal_t* ms = NULL;
	size_t ocalloc_size = sizeof(ms_ocall_log_fatal_t);
	void *__tmp = NULL;


	CHECK_ENCLAVE_POINTER(buf, _len_buf);

	ocalloc_size += (buf != NULL) ? _len_buf : 0;

	__tmp = sgx_ocalloc(ocalloc_size);
	if (__tmp == NULL) {
		sgx_ocfree();
		return SGX_ERROR_UNEXPECTED;
	}
	ms = (ms_ocall_log_fatal_t*)__tmp;
	__tmp = (void *)((size_t)__tmp + sizeof(ms_ocall_log_fatal_t));
	ocalloc_size -= sizeof(ms_ocall_log_fatal_t);

	if (buf != NULL) {
		ms->ms_buf = (const char*)__tmp;
		if (memcpy_s(__tmp, ocalloc_size, buf, _len_buf)) {
			sgx_ocfree();
			return SGX_ERROR_UNEXPECTED;
		}
		__tmp = (void *)((size_t)__tmp + _len_buf);
		ocalloc_size -= _len_buf;
	} else {
		ms->ms_buf = NULL;
	}
	
	status = sgx_ocall(10, ms);

	if (status == SGX_SUCCESS) {
	}
	sgx_ocfree();
	return status;
}

sgx_status_t SGX_CDECL ocall_fopen(int* retval, _int64* file, const char* file_name, const char* mode)
{
	sgx_status_t status = SGX_SUCCESS;
	size_t _len_file = sizeof(_int64);
	size_t _len_file_name = file_name ? strlen(file_name) + 1 : 0;
	size_t _len_mode = mode ? strlen(mode) + 1 : 0;

	ms_ocall_fopen_t* ms = NULL;
	size_t ocalloc_size = sizeof(ms_ocall_fopen_t);
	void *__tmp = NULL;

	void *__tmp_file = NULL;

	CHECK_ENCLAVE_POINTER(file, _len_file);
	CHECK_ENCLAVE_POINTER(file_name, _len_file_name);
	CHECK_ENCLAVE_POINTER(mode, _len_mode);

	ocalloc_size += (file != NULL) ? _len_file : 0;
	ocalloc_size += (file_name != NULL) ? _len_file_name : 0;
	ocalloc_size += (mode != NULL) ? _len_mode : 0;

	__tmp = sgx_ocalloc(ocalloc_size);
	if (__tmp == NULL) {
		sgx_ocfree();
		return SGX_ERROR_UNEXPECTED;
	}
	ms = (ms_ocall_fopen_t*)__tmp;
	__tmp = (void *)((size_t)__tmp + sizeof(ms_ocall_fopen_t));
	ocalloc_size -= sizeof(ms_ocall_fopen_t);

	if (file != NULL) {
		ms->ms_file = (_int64*)__tmp;
		__tmp_file = __tmp;
		memset(__tmp_file, 0, _len_file);
		__tmp = (void *)((size_t)__tmp + _len_file);
		ocalloc_size -= _len_file;
	} else {
		ms->ms_file = NULL;
	}
	
	if (file_name != NULL) {
		ms->ms_file_name = (const char*)__tmp;
		if (memcpy_s(__tmp, ocalloc_size, file_name, _len_file_name)) {
			sgx_ocfree();
			return SGX_ERROR_UNEXPECTED;
		}
		__tmp = (void *)((size_t)__tmp + _len_file_name);
		ocalloc_size -= _len_file_name;
	} else {
		ms->ms_file_name = NULL;
	}
	
	if (mode != NULL) {
		ms->ms_mode = (const char*)__tmp;
		if (memcpy_s(__tmp, ocalloc_size, mode, _len_mode)) {
			sgx_ocfree();
			return SGX_ERROR_UNEXPECTED;
		}
		__tmp = (void *)((size_t)__tmp + _len_mode);
		ocalloc_size -= _len_mode;
	} else {
		ms->ms_mode = NULL;
	}
	
	status = sgx_ocall(11, ms);

	if (status == SGX_SUCCESS) {
		if (retval) *retval = ms->ms_retval;
		if (file) {
			if (memcpy_s((void*)file, _len_file, __tmp_file, _len_file)) {
				sgx_ocfree();
				return SGX_ERROR_UNEXPECTED;
			}
		}
	}
	sgx_ocfree();
	return status;
}

sgx_status_t SGX_CDECL ocall_fclose(int* retval, _int64 file)
{
	sgx_status_t status = SGX_SUCCESS;

	ms_ocall_fclose_t* ms = NULL;
	size_t ocalloc_size = sizeof(ms_ocall_fclose_t);
	void *__tmp = NULL;


	__tmp = sgx_ocalloc(ocalloc_size);
	if (__tmp == NULL) {
		sgx_ocfree();
		return SGX_ERROR_UNEXPECTED;
	}
	ms = (ms_ocall_fclose_t*)__tmp;
	__tmp = (void *)((size_t)__tmp + sizeof(ms_ocall_fclose_t));
	ocalloc_size -= sizeof(ms_ocall_fclose_t);

	ms->ms_file = file;
	status = sgx_ocall(12, ms);

	if (status == SGX_SUCCESS) {
		if (retval) *retval = ms->ms_retval;
	}
	sgx_ocfree();
	return status;
}

sgx_status_t SGX_CDECL ocall_fputs(int* retval, _int64 file, const char* buf)
{
	sgx_status_t status = SGX_SUCCESS;
	size_t _len_buf = buf ? strlen(buf) + 1 : 0;

	ms_ocall_fputs_t* ms = NULL;
	size_t ocalloc_size = sizeof(ms_ocall_fputs_t);
	void *__tmp = NULL;


	CHECK_ENCLAVE_POINTER(buf, _len_buf);

	ocalloc_size += (buf != NULL) ? _len_buf : 0;

	__tmp = sgx_ocalloc(ocalloc_size);
	if (__tmp == NULL) {
		sgx_ocfree();
		return SGX_ERROR_UNEXPECTED;
	}
	ms = (ms_ocall_fputs_t*)__tmp;
	__tmp = (void *)((size_t)__tmp + sizeof(ms_ocall_fputs_t));
	ocalloc_size -= sizeof(ms_ocall_fputs_t);

	ms->ms_file = file;
	if (buf != NULL) {
		ms->ms_buf = (const char*)__tmp;
		if (memcpy_s(__tmp, ocalloc_size, buf, _len_buf)) {
			sgx_ocfree();
			return SGX_ERROR_UNEXPECTED;
		}
		__tmp = (void *)((size_t)__tmp + _len_buf);
		ocalloc_size -= _len_buf;
	} else {
		ms->ms_buf = NULL;
	}
	
	status = sgx_ocall(13, ms);

	if (status == SGX_SUCCESS) {
		if (retval) *retval = ms->ms_retval;
	}
	sgx_ocfree();
	return status;
}

sgx_status_t SGX_CDECL ocall_fseek(int* retval, _int64 file, long int offset, int origin)
{
	sgx_status_t status = SGX_SUCCESS;

	ms_ocall_fseek_t* ms = NULL;
	size_t ocalloc_size = sizeof(ms_ocall_fseek_t);
	void *__tmp = NULL;


	__tmp = sgx_ocalloc(ocalloc_size);
	if (__tmp == NULL) {
		sgx_ocfree();
		return SGX_ERROR_UNEXPECTED;
	}
	ms = (ms_ocall_fseek_t*)__tmp;
	__tmp = (void *)((size_t)__tmp + sizeof(ms_ocall_fseek_t));
	ocalloc_size -= sizeof(ms_ocall_fseek_t);

	ms->ms_file = file;
	ms->ms_offset = offset;
	ms->ms_origin = origin;
	status = sgx_ocall(14, ms);

	if (status == SGX_SUCCESS) {
		if (retval) *retval = ms->ms_retval;
	}
	sgx_ocfree();
	return status;
}

sgx_status_t SGX_CDECL ocall_ftell(long int* retval, _int64 file)
{
	sgx_status_t status = SGX_SUCCESS;

	ms_ocall_ftell_t* ms = NULL;
	size_t ocalloc_size = sizeof(ms_ocall_ftell_t);
	void *__tmp = NULL;


	__tmp = sgx_ocalloc(ocalloc_size);
	if (__tmp == NULL) {
		sgx_ocfree();
		return SGX_ERROR_UNEXPECTED;
	}
	ms = (ms_ocall_ftell_t*)__tmp;
	__tmp = (void *)((size_t)__tmp + sizeof(ms_ocall_ftell_t));
	ocalloc_size -= sizeof(ms_ocall_ftell_t);

	ms->ms_file = file;
	status = sgx_ocall(15, ms);

	if (status == SGX_SUCCESS) {
		if (retval) *retval = ms->ms_retval;
	}
	sgx_ocfree();
	return status;
}

sgx_status_t SGX_CDECL ocall_fread(size_t* retval, _int64 file, void* buf, int buf_len, size_t element_size, size_t element_count)
{
	sgx_status_t status = SGX_SUCCESS;
	size_t _len_buf = buf_len;

	ms_ocall_fread_t* ms = NULL;
	size_t ocalloc_size = sizeof(ms_ocall_fread_t);
	void *__tmp = NULL;

	void *__tmp_buf = NULL;

	CHECK_ENCLAVE_POINTER(buf, _len_buf);

	ocalloc_size += (buf != NULL) ? _len_buf : 0;

	__tmp = sgx_ocalloc(ocalloc_size);
	if (__tmp == NULL) {
		sgx_ocfree();
		return SGX_ERROR_UNEXPECTED;
	}
	ms = (ms_ocall_fread_t*)__tmp;
	__tmp = (void *)((size_t)__tmp + sizeof(ms_ocall_fread_t));
	ocalloc_size -= sizeof(ms_ocall_fread_t);

	ms->ms_file = file;
	if (buf != NULL) {
		ms->ms_buf = (void*)__tmp;
		__tmp_buf = __tmp;
		memset(__tmp_buf, 0, _len_buf);
		__tmp = (void *)((size_t)__tmp + _len_buf);
		ocalloc_size -= _len_buf;
	} else {
		ms->ms_buf = NULL;
	}
	
	ms->ms_buf_len = buf_len;
	ms->ms_element_size = element_size;
	ms->ms_element_count = element_count;
	status = sgx_ocall(16, ms);

	if (status == SGX_SUCCESS) {
		if (retval) *retval = ms->ms_retval;
		if (buf) {
			if (memcpy_s((void*)buf, _len_buf, __tmp_buf, _len_buf)) {
				sgx_ocfree();
				return SGX_ERROR_UNEXPECTED;
			}
		}
	}
	sgx_ocfree();
	return status;
}

sgx_status_t SGX_CDECL ocall_fgets(char** retval, _int64 file, char* buf, int buf_len)
{
	sgx_status_t status = SGX_SUCCESS;
	size_t _len_buf = buf_len;

	ms_ocall_fgets_t* ms = NULL;
	size_t ocalloc_size = sizeof(ms_ocall_fgets_t);
	void *__tmp = NULL;

	void *__tmp_buf = NULL;

	CHECK_ENCLAVE_POINTER(buf, _len_buf);

	ocalloc_size += (buf != NULL) ? _len_buf : 0;

	__tmp = sgx_ocalloc(ocalloc_size);
	if (__tmp == NULL) {
		sgx_ocfree();
		return SGX_ERROR_UNEXPECTED;
	}
	ms = (ms_ocall_fgets_t*)__tmp;
	__tmp = (void *)((size_t)__tmp + sizeof(ms_ocall_fgets_t));
	ocalloc_size -= sizeof(ms_ocall_fgets_t);

	ms->ms_file = file;
	if (buf != NULL) {
		ms->ms_buf = (char*)__tmp;
		__tmp_buf = __tmp;
		memset(__tmp_buf, 0, _len_buf);
		__tmp = (void *)((size_t)__tmp + _len_buf);
		ocalloc_size -= _len_buf;
	} else {
		ms->ms_buf = NULL;
	}
	
	ms->ms_buf_len = buf_len;
	status = sgx_ocall(17, ms);

	if (status == SGX_SUCCESS) {
		if (retval) *retval = ms->ms_retval;
		if (buf) {
			if (memcpy_s((void*)buf, _len_buf, __tmp_buf, _len_buf)) {
				sgx_ocfree();
				return SGX_ERROR_UNEXPECTED;
			}
		}
	}
	sgx_ocfree();
	return status;
}

sgx_status_t SGX_CDECL ocall_is_dir_exsit(int* retval, const char* dri_name)
{
	sgx_status_t status = SGX_SUCCESS;
	size_t _len_dri_name = dri_name ? strlen(dri_name) + 1 : 0;

	ms_ocall_is_dir_exsit_t* ms = NULL;
	size_t ocalloc_size = sizeof(ms_ocall_is_dir_exsit_t);
	void *__tmp = NULL;


	CHECK_ENCLAVE_POINTER(dri_name, _len_dri_name);

	ocalloc_size += (dri_name != NULL) ? _len_dri_name : 0;

	__tmp = sgx_ocalloc(ocalloc_size);
	if (__tmp == NULL) {
		sgx_ocfree();
		return SGX_ERROR_UNEXPECTED;
	}
	ms = (ms_ocall_is_dir_exsit_t*)__tmp;
	__tmp = (void *)((size_t)__tmp + sizeof(ms_ocall_is_dir_exsit_t));
	ocalloc_size -= sizeof(ms_ocall_is_dir_exsit_t);

	if (dri_name != NULL) {
		ms->ms_dri_name = (const char*)__tmp;
		if (memcpy_s(__tmp, ocalloc_size, dri_name, _len_dri_name)) {
			sgx_ocfree();
			return SGX_ERROR_UNEXPECTED;
		}
		__tmp = (void *)((size_t)__tmp + _len_dri_name);
		ocalloc_size -= _len_dri_name;
	} else {
		ms->ms_dri_name = NULL;
	}
	
	status = sgx_ocall(18, ms);

	if (status == SGX_SUCCESS) {
		if (retval) *retval = ms->ms_retval;
	}
	sgx_ocfree();
	return status;
}

sgx_status_t SGX_CDECL ocall_make_dir(int* retval, const char* dir_name)
{
	sgx_status_t status = SGX_SUCCESS;
	size_t _len_dir_name = dir_name ? strlen(dir_name) + 1 : 0;

	ms_ocall_make_dir_t* ms = NULL;
	size_t ocalloc_size = sizeof(ms_ocall_make_dir_t);
	void *__tmp = NULL;


	CHECK_ENCLAVE_POINTER(dir_name, _len_dir_name);

	ocalloc_size += (dir_name != NULL) ? _len_dir_name : 0;

	__tmp = sgx_ocalloc(ocalloc_size);
	if (__tmp == NULL) {
		sgx_ocfree();
		return SGX_ERROR_UNEXPECTED;
	}
	ms = (ms_ocall_make_dir_t*)__tmp;
	__tmp = (void *)((size_t)__tmp + sizeof(ms_ocall_make_dir_t));
	ocalloc_size -= sizeof(ms_ocall_make_dir_t);

	if (dir_name != NULL) {
		ms->ms_dir_name = (const char*)__tmp;
		if (memcpy_s(__tmp, ocalloc_size, dir_name, _len_dir_name)) {
			sgx_ocfree();
			return SGX_ERROR_UNEXPECTED;
		}
		__tmp = (void *)((size_t)__tmp + _len_dir_name);
		ocalloc_size -= _len_dir_name;
	} else {
		ms->ms_dir_name = NULL;
	}
	
	status = sgx_ocall(19, ms);

	if (status == SGX_SUCCESS) {
		if (retval) *retval = ms->ms_retval;
	}
	sgx_ocfree();
	return status;
}

sgx_status_t SGX_CDECL u_sgxssl_ftime64(void* timeptr, uint32_t timeb64Len)
{
	sgx_status_t status = SGX_SUCCESS;
	size_t _len_timeptr = timeb64Len;

	ms_u_sgxssl_ftime64_t* ms = NULL;
	size_t ocalloc_size = sizeof(ms_u_sgxssl_ftime64_t);
	void *__tmp = NULL;

	void *__tmp_timeptr = NULL;

	CHECK_ENCLAVE_POINTER(timeptr, _len_timeptr);

	ocalloc_size += (timeptr != NULL) ? _len_timeptr : 0;

	__tmp = sgx_ocalloc(ocalloc_size);
	if (__tmp == NULL) {
		sgx_ocfree();
		return SGX_ERROR_UNEXPECTED;
	}
	ms = (ms_u_sgxssl_ftime64_t*)__tmp;
	__tmp = (void *)((size_t)__tmp + sizeof(ms_u_sgxssl_ftime64_t));
	ocalloc_size -= sizeof(ms_u_sgxssl_ftime64_t);

	if (timeptr != NULL) {
		ms->ms_timeptr = (void*)__tmp;
		__tmp_timeptr = __tmp;
		memset(__tmp_timeptr, 0, _len_timeptr);
		__tmp = (void *)((size_t)__tmp + _len_timeptr);
		ocalloc_size -= _len_timeptr;
	} else {
		ms->ms_timeptr = NULL;
	}
	
	ms->ms_timeb64Len = timeb64Len;
	status = sgx_ocall(20, ms);

	if (status == SGX_SUCCESS) {
		if (timeptr) {
			if (memcpy_s((void*)timeptr, _len_timeptr, __tmp_timeptr, _len_timeptr)) {
				sgx_ocfree();
				return SGX_ERROR_UNEXPECTED;
			}
		}
	}
	sgx_ocfree();
	return status;
}

#ifdef _MSC_VER
#pragma warning(pop)
#endif
